#ifndef __SRF02_H__
#define __SRF02_H__

/*
 *****************************************************************************
 *
 * File Name    : srf02.h
 * Title        : Ultrasound Range Finder Sensor
 * Author       : Martin Metal
 * Date         : 09/04/2012
 * Revised      : 09/04/2012
 * Version      : 1.0
 * Target MCU   : Atmel AVR ATMega8
 * Editor Tabs  : 3
 * Description  : Header file for Parallax range finder, i2c or serial bus.
 *
 * Range finder is a sonar system transmitting bursts of 40kHz signal to map
 * the terrain in front of the sensor. It can measure the distance of the object 
 * between 10 - 600 cm.   
 *
 * This element uses i2c bus to connect to the ucontroller. The base address
 * of the device is 0xE0 for writing and 0xE1 for reading (assumed). 
 * The structure of the register for reading looks like this:
 * 
 *  +------------------------------------------+
 *  | Reading Registers                        |
 *  +---------+--------------------------------+
 *  | Address |   Purpose                      |
 *  |---------+--------------------------------|
 *  |  0x00   |  Software revision             |
 *  |  0x02   |  Measured distance (high byte) |
 *  |  0x03   |  Measured distance (low byte)  |
 *  |  0x04   |  Autotune min (high byte)      |
 *  |  0x05   |  Autotune min (low byte)       |
 *  +---------+--------------------------------+
 *
 *  +------------------------------------------+
 *  | Writing Registers                        |
 *  +---------+--------------------------------+
 *  | Address |   Purpose                      |
 *  |---------+--------------------------------|
 *  |  0x00   |  Command Register (see table)  |
 *  +---------+--------------------------------+
 *
 *     COMMANDS
 *  +---------+-------------------------------------------+
 *  | Command |  Action                                   |
 *  +---------+-------------------------------------------+
 *  |  0x50   | Real Ranging Mode, result in inches       |
 *  |  0x51   | Real Ranging Mode, result in centimeters  |
 *  |  0x52   | Real Ranging Mode, result in microseconds |
 *  |  0x60   | Restart the device                        |
 *  |         |                                           |
 *  |  0xA0   | change i2c address command, 1st byte      |
 *  |  0xA5   | change i2c address command, 3rd byte      |
 *  |  0xAA   | change i2c address command, 2nd byte      |
 *  +---------+-------------------------------------------+
 *
 * The range finder is connected to the controller by I2C interface. The
 * supported speed is 100kHz mode (I2C slow). The implementation is using
 * standard I2C library using the I2C interrupts. The application is already
 * using the interrupts for USART traffic and servo shield control. Therefore
 * the access to I2C bus must be synchronized with the counter compare match
 * interrupt so that the timing to the servos is not impacted by interrupts 
 * generated by ranging device.
 *
 * IMPORTANT
 * ---------
 * This device requests explicit notification before STOP signal is sent. The
 * master must request the last fetched byte with the NACK bit set. All the
 * preceding transaction are completed with ACK bit otherwise. Omitting the NACK
 * flag before accessing the last fetched byte the slave does not accept the
 * following STOP signal and bus enters 0xF8 status -> no relevant information
 * available. The next request for access the device fails then.
 *
 * ERROR Codes reading SRF02, masked by 0x0F
 * ===================---===================
 *
 * 0x01 - sending I2C start condition failed. It is the first call after
 *        initializing I2C bus. Typically the bus was not available for
 *        sending the start condition, the preceding STOP was not successful 
 *        This condition can frequently occur when requesting the ACK for all
 *        bytes requested from SRF device. Last byte must be always requested
 *        with the NACK flag set.
 *
 * 0x02 - Error initializing the address that should be read. Address setting 
 *        requires two I2C sequences, first sending the request for write
 *        followed by the device address. This error report problem when
 *        requesting the write access to the I2C device.
 *
 * 0x03 - Error transmitting the address. I2C device got a write request in the
 *        preceding I2C request and this error indicates problems when
 *        transmitting the value of the address itself. 
 * 
 * 0x04 - Error trying to repeat the start condition without releasing the I2C
 *        line. This error can occur when reading the I2C device. Restart
 *        condition is sent after changing the access mode (write/read).
 *
 * 0x05 - Error requesting the read mode. The I2C cannot acquire the read access
 *        to the specific device. It can be a non existent device or requesting
 *        the I2C operation without sending the ACK/NACK request. 
 *
 * 0x06 - Error reading the data from a specified address. The reading is 
 *        sensitive for acknowledgment presence. The master must instruct the
 *        I2C device whether master intends to continue reading or wants to
 *        terminate the communication. Most of the I2C devices requires the
 *        master to request the last data byte with the flag NACK. The client
 *        then sends NACK and expects STOP signal to follow. If the ACK is
 *        required instead, then I2C slave sends the data and internally expect
 *        the session to continue and therefore is not ready to accept the STOP
 *        condition. The STOP is ignored and slave keeps the SDA line low
 *        expecting next reading access from master. This behavior is not
 *        characteristic for EEPROMS, they react on STOP signal even after ACK
 *        or NACK in data retrieval procedure. However other devices might get
 *        strict about NACK vs. ACK in the last fetched byte. SRF02 is inside
 *        this category and requires explicit notification in the form of NACK
 *        request before receiving the STOP condition. This error occurs when 
 *        the device does not expect the NACK/ACK status at the specific state.
 *
 * 0x07 - Error sending the stop condition. This error typically indicates the 
 *        wrong communication model used when fetching data from slave. Slave
 *        might require a warning before the stop state is issued by a master.
 *        This warning is transmitted to slave by master in I2C transaction
 *        immediately preceding the stop transaction. The warning is a specific
 *        request for acknowledgement bit requested by master in data access
 *        transaction. See description of error 0x05 for further details.
 *
 * The I2C specific error is obtained when using the mask 0xF8. The I2C errors
 * are documented inside the I2C (TWI) section of the data sheet of Atmels
 * Mega8. The error codes are available in the i2c.h file additionally.
 */

#define HI_BYTE                        0x00
#define LO_BYTE                        0x01

#define SRF02_W                        0xE0
#define SRF02_R                        0xE1

#define SRF02_CMD_GET_RANGE_CM         0x51

#define SRF02_OK                       0x00
#define SRF02_ERROR                    0x01

#define SRF02_CMD_ADDR                 0x00
#define SRF02_DISTANCE_HI              0x02
#define SRF02_DISTANCE_LO              0x03
#define SRF02_MIN_DISTANCE_HI          0x04
#define SRF02_MIN_DISTANCE_LO          0x05

#define SRF02_DATA_NOT_READY           0x00
#define SRF02_DATA_READY               0x01
#define SRF02_VERSION                  0x06

#define SRF02_WRONG_REGISTER           0xD0

enum ack_t {
   ACK = 0,
   NACK
};
typedef enum ack_t ack_t;

//uint16_t i2c_srf02_read_word( uint8_t addr );
/* Is not used in this implementation and therefore commented out
 */
uint8_t i2c_srf02_write_byte(uint8_t addr, uint8_t byte);
/* Writes single byte at spefifid location. Error status is
 * returned.
 */


uint8_t i2c_srf02_read_byte( uint8_t addr, ack_t );
/* fetches single byte from I2C slave. This function cannot return the 
 * error status if it occur. The function returns zero if an error
 * condition occur. User must be careful when working with the ack 
 * parameter. See the important note in this header for further
 * details.
 *
 * Paramaters:
 *    addr: address of the register that the data is fetched from.
 *    ack : acknowledgement flag [ACK | NACK].
 *
 * Return value: fetched byte. This function cannot deliver the error
 * code if something goes wrong. The fucntion always return 0 if
 * internal error occurs
 */
 

uint8_t i2c_srf02_read_byte_ex( uint8_t addr, uint8_t flags, uint8_t * data );
/* Fetches single byte via I2C bus from slave. This function is actually
 * very similar to the function i2c_srf02_read_byte, but additionally
 * provides mechanism to deliver the error code, if something goes wrong.
 * This function is designed for device debugging, where the error status
 * might help to identify the reason for failure. User can also specify
 * the complete TWI flags that shall be used in this transaction.
 */

//uint16_t srf02_get_range( void );
uint8_t srf02_ping( void );
uint8_t srf02_is_data_ready( void );
uint8_t srf02_get_version( void );
uint8_t srf02_get_range_lo( void );
uint8_t srf02_get_range_hi( void );
uint8_t srf02_get_range_byte( uint8_t, uint8_t* );

#ifdef _SRF02_DEBUG
uint8_t srf02_get_version_ex( uint8_t * data );
#endif


#endif // __SRF02_H_
